import { Content, ContentType } from '../../types/document';
import { 
  SearchConfig, 
  SearchResult, 
  SearchHighlight, 
  QueryTerm, 
  SearchIndexItem,
  SearchServiceResult,
  SEARCH_LIMITS
} from './types';
import { simpleStorageAdapter } from '../export/simpleStorageAdapter';

export class FullTextSearchEngine {
  private searchIndex: Map<string, SearchIndexItem> = new Map();
  private initialized = false;

  /**
   * 初始化搜索引擎
   */
  async initialize(): Promise<void> {
    if (this.initialized) return;

    try {
      const result = await simpleStorageAdapter.get<SearchIndexItem[]>('rmzf:search:index');
      if (result.success && result.data) {
        this.searchIndex.clear();
        for (const item of result.data) {
          this.searchIndex.set(item.id, item);
        }
      }
      this.initialized = true;
      console.log('[FullTextSearchEngine] 搜索引擎初始化完成，索引文档数:', this.searchIndex.size);
    } catch (error) {
      console.error('[FullTextSearchEngine] 初始化失败:', error);
      throw error;
    }
  }

  /**
   * 执行全文搜索
   */
  async search(documents: Content[], config: SearchConfig): Promise<SearchResult[]> {
    await this.initialize();

    if (!config.query.trim()) {
      return this.sortDocuments(documents, config).map(doc => ({
        document: doc,
        score: 1,
        highlights: [],
        matchedFields: []
      }));
    }

    const queryTerms = this.processQuery(config.query);
    const results: SearchResult[] = [];

    for (const document of documents) {
      const relevanceScore = await this.calculateRelevance(document, queryTerms);
      if (relevanceScore > 0) {
        const highlights = this.generateHighlights(document, queryTerms);
        const matchedFields = this.getMatchedFields(document, queryTerms);
        
        results.push({
          document,
          score: relevanceScore,
          highlights,
          matchedFields
        });
      }
    }

    // 按相关性排序
    return this.sortResults(results, config);
  }

  /**
   * 更新文档索引
   */
  async updateDocumentIndex(document: Content): Promise<void> {
    await this.initialize();

    const indexItem = await this.buildDocumentIndex(document);
    this.searchIndex.set(document.id, indexItem);
    
    // 保存到存储
    await this.saveIndex();
    console.log('[FullTextSearchEngine] 文档索引已更新:', document.id);
  }

  /**
   * 删除文档索引
   */
  async removeDocumentIndex(documentId: string): Promise<void> {
    await this.initialize();

    this.searchIndex.delete(documentId);
    await this.saveIndex();
    console.log('[FullTextSearchEngine] 文档索引已删除:', documentId);
  }

  /**
   * 重建全部索引
   */
  async rebuildIndex(documents: Content[]): Promise<void> {
    console.log('[FullTextSearchEngine] 开始重建搜索索引...');
    this.searchIndex.clear();

    for (const document of documents) {
      const indexItem = await this.buildDocumentIndex(document);
      this.searchIndex.set(document.id, indexItem);
    }

    await this.saveIndex();
    console.log('[FullTextSearchEngine] 搜索索引重建完成，文档数:', documents.length);
  }

  /**
   * 获取搜索建议
   */
  async getSuggestions(query: string): Promise<string[]> {
    await this.initialize();

    if (!query.trim() || query.length < 2) return [];

    const suggestions = new Set<string>();
    const queryLower = query.toLowerCase();

    // 从索引中提取相关词汇
    for (const [, indexItem] of this.searchIndex) {
      // 从标题提取建议
      if (indexItem.title.toLowerCase().includes(queryLower)) {
        suggestions.add(indexItem.title);
      }

      // 从分词结果提取建议
      for (const token of indexItem.tokens) {
        if (token.toLowerCase().includes(queryLower) && token.length >= 2) {
          suggestions.add(token);
        }
      }

      if (suggestions.size >= 10) break;
    }

    return Array.from(suggestions).slice(0, 10);
  }

  /**
   * 处理查询字符串，提取查询词
   */
  private processQuery(query: string): QueryTerm[] {
    const queryTerms: QueryTerm[] = [];
    const cleanQuery = query.trim().toLowerCase();

    // 简单的分词处理（字符级别）
    const tokens = this.tokenize(cleanQuery);
    
    for (const token of tokens) {
      if (token.length >= 1) {
        queryTerms.push({
          term: token,
          weight: token.length > 1 ? 1 : 0.5 // 单字符权重较低
        });
      }
    }

    return queryTerms;
  }

  /**
   * 简单分词器
   */
  private tokenize(text: string): string[] {
    const tokens: string[] = [];
    
    // 提取连续的中文字符
    const chineseMatches = text.match(/[\u4e00-\u9fff]+/g) || [];
    for (const match of chineseMatches) {
      // 添加整个词
      tokens.push(match);
      // 添加单个字符（用于模糊匹配）
      for (const char of match) {
        tokens.push(char);
      }
    }

    // 提取英文单词
    const englishMatches = text.match(/[a-zA-Z]+/g) || [];
    tokens.push(...englishMatches);

    // 提取数字
    const numberMatches = text.match(/\\d+/g) || [];
    tokens.push(...numberMatches);

    return [...new Set(tokens)]; // 去重
  }

  /**
   * 计算文档相关性
   */
  private async calculateRelevance(document: Content, queryTerms: QueryTerm[]): Promise<number> {
    let totalScore = 0;
    const indexItem = this.searchIndex.get(document.id);

    for (const queryTerm of queryTerms) {
      let termScore = 0;

      // 标题匹配（权重较高）
      const titleScore = this.calculateFieldScore(document.title, queryTerm.term, 2.0);
      termScore += titleScore;

      // 内容匹配
      const contentText = this.extractContentText(document);
      const contentScore = this.calculateFieldScore(contentText, queryTerm.term, 1.0);
      termScore += contentScore;

      // 使用TF-IDF权重（如果有索引）
      if (indexItem && indexItem.tfidf[queryTerm.term]) {
        termScore *= indexItem.tfidf[queryTerm.term];
      }

      totalScore += termScore * queryTerm.weight;
    }

    return totalScore;
  }

  /**
   * 计算字段匹配分数
   */
  private calculateFieldScore(fieldText: string, term: string, fieldWeight: number): number {
    if (!fieldText || !term) return 0;

    const text = fieldText.toLowerCase();
    const searchTerm = term.toLowerCase();
    
    // 完全匹配
    if (text.includes(searchTerm)) {
      const occurrences = (text.match(new RegExp(searchTerm, 'g')) || []).length;
      const termFrequency = occurrences / Math.max(text.length / searchTerm.length, 1);
      
      // 位置加权：越靠前权重越高
      const firstIndex = text.indexOf(searchTerm);
      const positionWeight = Math.max(0.1, 1 - (firstIndex / text.length));
      
      return termFrequency * fieldWeight * positionWeight;
    }

    return 0;
  }

  /**
   * 生成搜索高亮
   */
  private generateHighlights(document: Content, queryTerms: QueryTerm[]): SearchHighlight[] {
    const highlights: SearchHighlight[] = [];

    for (const queryTerm of queryTerms) {
      // 标题高亮
      const titleHighlights = this.findHighlights(document.title, queryTerm.term, 'title');
      highlights.push(...titleHighlights);

      // 内容高亮
      const contentText = this.extractContentText(document);
      const contentHighlights = this.findHighlights(contentText, queryTerm.term, 'content');
      highlights.push(...contentHighlights.slice(0, 5)); // 限制内容高亮数量
    }

    return highlights;
  }

  /**
   * 查找文本中的高亮位置
   */
  private findHighlights(text: string, term: string, field: 'title' | 'content'): SearchHighlight[] {
    const highlights: SearchHighlight[] = [];
    if (!text || !term) return highlights;

    const lowerText = text.toLowerCase();
    const lowerTerm = term.toLowerCase();
    let index = 0;

    while (index < lowerText.length) {
      const found = lowerText.indexOf(lowerTerm, index);
      if (found === -1) break;

      // 提取上下文
      const contextStart = Math.max(0, found - 20);
      const contextEnd = Math.min(text.length, found + term.length + 20);
      const contextText = text.substring(contextStart, contextEnd);

      highlights.push({
        field,
        text: contextText,
        start: found - contextStart,
        end: found - contextStart + term.length
      });

      index = found + 1;
      if (highlights.length >= 10) break; // 限制高亮数量
    }

    return highlights;
  }

  /**
   * 获取匹配的字段
   */
  private getMatchedFields(document: Content, queryTerms: QueryTerm[]): string[] {
    const fields: string[] = [];

    for (const queryTerm of queryTerms) {
      if (document.title.toLowerCase().includes(queryTerm.term.toLowerCase())) {
        fields.push('title');
      }
      
      const contentText = this.extractContentText(document);
      if (contentText.toLowerCase().includes(queryTerm.term.toLowerCase())) {
        fields.push('content');
      }
    }

    return [...new Set(fields)];
  }

  /**
   * 提取文档内容文本
   */
  private extractContentText(document: Content): string {
    switch (document.type) {
      case ContentType.TEXT_DOCUMENT:
        // 如果是HTML内容，提取纯文本
        if (document.data.content?.includes('<')) {
          const globalDoc = typeof window !== 'undefined' ? window.document : null;
          if (globalDoc) {
            const tempDiv = globalDoc.createElement('div');
            tempDiv.innerHTML = document.data.content;
            return tempDiv.textContent || tempDiv.innerText || '';
          }
          // 简单的HTML标签去除
          return document.data.content.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
        }
        return document.data.content || '';
      default:
        return '';
    }
  }

  /**
   * 构建文档索引项
   */
  private async buildDocumentIndex(document: Content): Promise<SearchIndexItem> {
    const title = document.title;
    const content = this.extractContentText(document);
    const tokens = this.tokenize(title + ' ' + content);
    
    // 计算TF-IDF权重（简化版本）
    const tfidf: {[token: string]: number} = {};
    const totalTokens = tokens.length;
    
    for (const token of tokens) {
      const tf = tokens.filter(t => t === token).length / totalTokens;
      // 简化的IDF计算：假设文档集合大小
      const idf = Math.log(Math.max(this.searchIndex.size, 1) / Math.max(this.getTokenDocumentCount(token), 1));
      tfidf[token] = tf * idf;
    }

    return {
      id: document.id,
      title,
      content,
      tokens: [...new Set(tokens)],
      tfidf,
      lastIndexed: Date.now()
    };
  }

  /**
   * 获取包含特定词汇的文档数量
   */
  private getTokenDocumentCount(token: string): number {
    let count = 0;
    for (const [, indexItem] of this.searchIndex) {
      if (indexItem.tokens.includes(token)) {
        count++;
      }
    }
    return Math.max(count, 1);
  }

  /**
   * 保存索引到存储
   */
  private async saveIndex(): Promise<void> {
    try {
      const indexArray = Array.from(this.searchIndex.values());
      await simpleStorageAdapter.set('rmzf:search:index', indexArray);
    } catch (error) {
      console.error('[FullTextSearchEngine] 保存索引失败:', error);
    }
  }

  /**
   * 排序搜索结果
   */
  private sortResults(results: SearchResult[], config: SearchConfig): SearchResult[] {
    return results.sort((a, b) => {
      switch (config.sortBy) {
        case 'relevance':
          return config.sortOrder === 'desc' ? b.score - a.score : a.score - b.score;
        case 'date':
          const dateA = a.document.updatedAt;
          const dateB = b.document.updatedAt;
          return config.sortOrder === 'desc' ? dateB - dateA : dateA - dateB;
        case 'title':
          const titleCompare = a.document.title.localeCompare(b.document.title);
          return config.sortOrder === 'desc' ? -titleCompare : titleCompare;
        case 'size':
          const sizeA = this.extractContentText(a.document).length;
          const sizeB = this.extractContentText(b.document).length;
          return config.sortOrder === 'desc' ? sizeB - sizeA : sizeA - sizeB;
        default:
          return 0;
      }
    });
  }

  /**
   * 排序文档（无搜索查询时）
   */
  private sortDocuments(documents: Content[], config: SearchConfig): Content[] {
    return [...documents].sort((a, b) => {
      switch (config.sortBy) {
        case 'date':
          return config.sortOrder === 'desc' ? b.updatedAt - a.updatedAt : a.updatedAt - b.updatedAt;
        case 'title':
          const titleCompare = a.title.localeCompare(b.title);
          return config.sortOrder === 'desc' ? -titleCompare : titleCompare;
        case 'size':
          const sizeA = this.extractContentText(a).length;
          const sizeB = this.extractContentText(b).length;
          return config.sortOrder === 'desc' ? sizeB - sizeA : sizeA - sizeB;
        default:
          return b.updatedAt - a.updatedAt; // 默认按时间倒序
      }
    });
  }
}